package com.yugao.fintech.antelope.mps.core.channel;

import com.yugao.fintech.antelope.base.config.core.ConfigFactory;
import com.yugao.fintech.antelope.base.model.enums.ConfigDefineEnum;
import com.yugao.fintech.antelope.base.model.enums.ConfigKeyEnum;
import com.yugao.fintech.antelope.base.model.module.config.ConfigInfo;
import com.yugao.fintech.antelope.base.model.module.config.param.BaseConfigParam;
import com.yugao.fintech.antelope.base.model.module.tenant.TenantContextHolder;
import com.yugao.fintech.antelope.mps.api.constatnts.ChannelCodeEnum;
import com.yugao.fintech.antelope.mps.api.constatnts.ChannelTypeEnum;
import com.yugao.fintech.antelope.mps.core.channel.client.BaseMsgChannelClient;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;


@Slf4j
@Component
public class ChannelClientManager {
    private static final Map<String, BaseMsgChannelClient> channelClientMap = new ConcurrentHashMap<>();

    @Autowired
    private ConfigFactory configFactory;

    private String getCacheKey(ConfigDefineEnum configDefine) {
        return TenantContextHolder.get().getTenantId() + configDefine.name();
    }

    private void createClient(ConfigDefineEnum configDefine) {
        String cacheKey = getCacheKey(configDefine);

        ConfigInfo config = configFactory.getConfigOfNonNull(configDefine);
        synchronized (cacheKey.intern()) {
            if (channelClientMap.containsKey(cacheKey)) {
                return;
            }

            // 这里获取到的配置是使能的配置, 所以根据使能的配置要获取到具体的渠道
            ChannelCodeEnum channelCode = ChannelCodeEnum.ofByBindConfig(config.getConfigKey());
            // 创建渠道客户端
            Class<? extends BaseMsgChannelClient> msgChannelClient = BaseMsgChannelClient.channelMap.get(channelCode);
            if (Objects.isNull(msgChannelClient)) {
                throw new BizException("消息渠道客户端 {} 尚未实现", channelCode);
            }

            // 获取使能的配置key
            ConfigKeyEnum enableConfigKey = ConfigKeyEnum.ofAndCheck(config.getConfigKey());
            MsgChannel msgChannel = new MsgChannel();
            msgChannel.setChannelCode(channelCode.getCode());
            msgChannel.setParamConfig(BaseConfigParam.jsonToObject(enableConfigKey, config.getConfigValue()));

            try {
                BaseMsgChannelClient baseMsgChannelClient = msgChannelClient.getDeclaredConstructor(MsgChannel.class)
                        .newInstance(msgChannel);
                baseMsgChannelClient.init();
                channelClientMap.put(cacheKey, baseMsgChannelClient);
            } catch (Exception e) {
                log.error("", e);
                throw new BizException(e.getMessage());
            }
        }
    }

    /**
     * 获取渠道客户端
     */
    public BaseMsgChannelClient getChannelClient(ChannelTypeEnum channelType) {
        String cacheKey = getCacheKey(channelType.getConfigDefine());
        if (!channelClientMap.containsKey(cacheKey)) {
            createClient(channelType.getConfigDefine());
        }
        return channelClientMap.get(cacheKey);
    }

    public void deleteChannelClient(String configKey) {
        ConfigDefineEnum configDefine = ConfigDefineEnum.ofByKey(configKey);
        ChannelTypeEnum channelTyp = ChannelTypeEnum.ofByConfigGDefine(configDefine);
        if (Objects.isNull(channelTyp)) {
            return;
        }
        channelClientMap.remove(getCacheKey(channelTyp.getConfigDefine()));
    }

    public void updateChannelClient(ConfigInfo configInfo) {
        // 这里只做删除操作, 下一次推送时候会自动初始化
        deleteChannelClient(configInfo.getConfigKey());
    }
}
